#include "precompiled.h"
#include "mainwindow.h"
using namespace std;
using namespace weo::ui;
using namespace weo::engine::item;
using namespace weo::engine::character;
using namespace weo::engine::optimization;

MainWindow::MainWindow(QWidget* parent /*= 0*/, Qt::WFlags flags /*= 0*/) : QMainWindow(parent, flags)
{
    m_Character = NULL;
    m_Optimizer = NULL;
    setupUi(this);
    QGridLayout *gridLayout = new QGridLayout;
    QSizePolicy qspminex;
    qspminex.setHorizontalPolicy(QSizePolicy::Expanding);
    m_GraphWidget = new GraphWidget(dockBottomWidget);
    dockBottomWidget->setWidget(m_GraphWidget);	
    for(int i = 0;i<weo::engine::Slotcount;i++)
    {
        int column = 0;
        QLabel *label = new QLabel(tr(weo::engine::Slotnames[i].c_str())+":");
        m_SlotLabels.push_back(label);
        gridLayout->addWidget(m_SlotLabels[i], i, column++);
        ItemComboBox<Item> *cbox = new ItemComboBox<Item>();
        cbox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
        cbox->setSizePolicy(qspminex);
        cbox->setEditable(false);
        cbox->setMinimumContentsLength(15);
        m_SlotCboxes.push_back(cbox);
        gridLayout->addWidget(m_SlotCboxes[i], i, column++);
        QLabel *gemlabel = new QLabel(tr("Gems:"));
        gemlabel->setText(tr("Gems:"));
        m_GemLabels.push_back(gemlabel);
        gridLayout->addWidget(m_GemLabels[i], i, column++);
        for(int k = 0;k<3;k++)
        {
            ItemComboBox<Item> *gembox = new ItemComboBox<Item>();
            gembox->setSizePolicy(qspminex);
            gembox->setEditable(false);
            gembox->setEnabled(false);
            gembox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
            gembox->setMinimumContentsLength(10);
            m_GemCboxes.push_back(gembox);
            gridLayout->addWidget(m_GemCboxes[i*3+k], i, column++);
        }
        QLabel *enchantlabel = new QLabel(tr("Enchant:"));
        m_EnchantLabels.push_back(enchantlabel);
        gridLayout->addWidget(m_EnchantLabels[i], i, column++);
        ItemComboBox<Enchant> *enchantbox = new ItemComboBox<Enchant>();
        enchantbox->setSizePolicy(qspminex);
        enchantbox->setEditable(false);
        enchantbox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
        enchantbox->setMinimumContentsLength(10);
        enchantbox->setEnabled(false);
        m_EnchantCboxes.push_back(enchantbox);
        gridLayout->addWidget(m_EnchantCboxes[i], i, column++);
        QCheckBox *checkbox = new QCheckBox(tr("Lock"));
        m_LockCheckBoxes.push_back(checkbox);
        gridLayout->addWidget(m_LockCheckBoxes[i], i, column++);
    }
    this->centralWidget()->setLayout(gridLayout);
    this->centralWidget()->setSizePolicy(qspminex);
    for(int i = 0;i<m_SlotCboxes.size();i++)
    {
        QObject::connect(m_SlotCboxes[i],SIGNAL(currentIndexChanged(int)),this,SLOT(SlotCBox_currentIndexChanged(int)));
        QObject::connect(m_SlotCboxes[i],SIGNAL(currentIndexChanged(int)),this,SLOT(UpdateTV(int)));
    }
    for(int i = 0;i<m_GemCboxes.size();i++)
    {
        QObject::connect(m_GemCboxes[i],SIGNAL(currentIndexChanged(int)),this,SLOT(UpdateTV(int)));
    }
    for(int i = 0;i<m_EnchantCboxes.size();i++)
    {
        QObject::connect(m_EnchantCboxes[i],SIGNAL(currentIndexChanged(int)),this,SLOT(UpdateTV(int)));
    }
    for(int i = 0;i<m_LockCheckBoxes.size();i++)
    {
        QObject::connect(m_LockCheckBoxes[i],SIGNAL(stateChanged(int)),this,SLOT(LockBox_checked(int)));
    }
    BWListDialog::loadXmlBWlist();
    Character::setBlacklist(BWListDialog::getBlacklist());
    Character::setWhitelist(BWListDialog::getWhitelist());
    loadData();
}
MainWindow::~MainWindow()
{
    BWListDialog::saveXmlBWlist();
}
void MainWindow::UpdateNotify(float value)
{
    boost::mutex::scoped_lock stl(m_Mutex);
    m_GraphWidget->addValue(value);
    QCoreApplication::postEvent(this,new QEvent(static_cast<QEvent::Type>(QEvent::User+1)));
}
void MainWindow::on_SaveButton_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save Equipment"), "", tr("XML Files (*.xml)"));
    if(fileName.size() > 0)
    {
        weo::engine::character::Equipment equip = getCurrentEquip();
        equip.saveEquipmentToFile(ClassCBox->currentText().toStdString(),BuildCBox->currentText().toStdString(),fileName.toStdString());
    }
}
void MainWindow::LockBox_checked(int state)
{
    QCheckBox *cbox = reinterpret_cast<QCheckBox *>(QObject::sender());
    int index = m_LockCheckBoxes.indexOf(cbox);
    m_Locks[index] = state == Qt::Checked ? true : false;
}
void MainWindow::on_LoadButton_clicked()
{
    Equipment equip;
    LoadCharDialog *lcd = new LoadCharDialog();
    lcd->exec();
    if(lcd->result() == QDialog::Accepted)
    {
        std::string url = lcd->GetUrl();
        std::pair<std::string,std::string> data("","");
        if(!lcd->FileMode())
        {
            data = equip.getEquipmentFromWeb(url);
        }
        else 
        {
            data = equip.loadEquipmentFromFile(url);
        }
        if(data.first.empty())
        {
            QMessageBox::critical(this,tr("Parsing Error"),tr("No proper Class/Build information found, aborting..."));
            return;
        }
        else if(data.second.empty())
        {
            if(data.first == ClassCBox->currentText().toStdString())
            {
                QMessageBox::warning(this,tr("Parsing Error"),tr("No proper Build information found, using current Build..."));
                data.second = BuildCBox->currentText().toStdString();
            }
            else
            {
                QMessageBox::warning(this,tr("Parsing Error"),tr("No proper Build information found, please select proper Build first and try again."));
                return;
            }
        }
        ClassCBox->setCurrentIndex(ClassCBox->findText(tr(data.first.c_str())));
        BuildCBox->setCurrentIndex(BuildCBox->findText(tr(data.second.c_str())));
        m_Character->evaluateBuffs();
        m_Character->evaluateEquip(equip.Items,equip.Gems,equip.Enchants);
        equip.Fitness = m_Character->evaluateTF();
        UpdateData(equip);
    }
}
void MainWindow::on_BWListButton_clicked()
{
    BWListDialog *bld = new BWListDialog();
    bld->setItems(m_Items);
    bld->exec();
    if(bld->result() == QDialog::Accepted)
    {
        bld->CleanUp();
        m_Character->setBlacklist(bld->getBlacklist());
        m_Character->setWhitelist(bld->getWhitelist());
        Equipment equip = getCurrentEquip();
        m_Items.clear();
        m_Character->filterEquip(m_Items);
        equip.filterEquip(m_Items);
        m_Character->evaluateBuffs();
        m_Character->evaluateEquip(equip.Items,equip.Gems,equip.Enchants);
        equip.Fitness = m_Character->evaluateTF();
        populateBoxes();
        UpdateData(equip);
    }
    delete bld;
}
void MainWindow::on_ConditionsButton_clicked()
{
    ConditionsDialog *cd = new ConditionsDialog();
    cd->setConditions(m_Character->Conditions());
    cd->exec();
    if(cd->result() == QDialog::Accepted)
    {
        Equipment equip = getCurrentEquip();
        m_Character->setConditions(cd->Conditions());
        m_Items.clear();
        m_Character->filterEquip(m_Items);
        equip.filterEquip(m_Items);
        m_Character->evaluateBuffs();
        m_Character->evaluateEquip(equip.Items,equip.Gems,equip.Enchants);
        equip.Fitness = m_Character->evaluateTF();
        populateBoxes();
        UpdateData(equip);
    }
    delete cd;
}
void MainWindow::on_EQVButton_clicked()
{
    EQVDialog *eqv = new EQVDialog();
    eqv->setAttributes(*m_Character->getAttributes(),m_Character->getAttributesStart(),m_Character->getAttributesStop());
    eqv->setCharacter(m_Character);
    eqv->setEquipment(getCurrentEquip());
    eqv->calcEQV();
    eqv->exec();
    delete eqv;
}
void MainWindow::on_BuffsButton_clicked()
{
    BuffsDialog *buffs = new BuffsDialog();
    bool bok = Buff::Bok();
    buffs->setBuffs(*m_Character->Buffs(),Buff::Bok());
    buffs->exec();
    if(buffs->result() == QDialog::Accepted)
    {
        Equipment equip = getCurrentEquip();
        m_Items.clear();     
        if(bok != buffs->getBok())
        {
            Buff::setBok(buffs->getBok());
            std::string classname = ClassCBox->currentText().toStdString();
            std::string buildname = BuildCBox->currentText().toStdString();
            m_Character = CharacterFactory::CallFactory<Character>(classname,buildname);
            m_Character->Database(Itemdatabase::getInstance());
        }
        m_Character->filterEquip(m_Items);
        equip.filterEquip(m_Items);
        buffs->getBuffs(m_Character->Buffs());
        m_Character->evaluateBuffs();
        m_Character->evaluateEquip(equip.Items,equip.Gems,equip.Enchants);
        equip.Fitness = m_Character->evaluateTF();
        populateBoxes();
        if(equip.Fitness > 0)
        {
            UpdateData(equip);
        }	
    }
    delete buffs;
}
void MainWindow::on_FilterButton_clicked()
{
    FilterItemsDialog *fid = new FilterItemsDialog();
    fid->setCharacter(m_Character);
    fid->setValues();
    fid->exec();
    if(fid->result() == QDialog::Accepted)
    {
        fid->getValues();
        Equipment equip = getCurrentEquip();
        m_Items.clear();
        m_Character->filterEquip(m_Items, equip);
        equip.filterEquip(m_Items);
        m_Character->evaluateBuffs();
        m_Character->evaluateEquip(equip.Items,equip.Gems,equip.Enchants);
        equip.Fitness = m_Character->evaluateTF();
        populateBoxes();
        if(equip.Fitness > 0)
        {
            UpdateData(equip);
        }
    }
    delete fid;
}
void MainWindow::on_CopyButton_clicked()
{
    QClipboard *clipboard = QApplication::clipboard();
    weo::engine::character::Equipment equip = getCurrentEquip();
    std::ostringstream oss;
    oss << "Items:" << endl;
    for(unsigned int i = 0;i<weo::engine::Slotcount;i++)
    {
        oss << "Item: " << equip.Items[i]->Name() << endl;
        for(unsigned int j = 0;j<equip.Items[i]->Sockets()->Count();j++)
        {
            oss << "\tGem: " << equip.Gems[i*3+j]->Name() << endl;
        }
        if(equip.Enchants[i] != NULL)
        {
            oss << "\tEnchant: " << equip.Enchants[i]->Name() << endl;
        }
    }
    oss << m_Character->targetValue() << ": " << equip.Fitness << endl;
    oss << "Attributes: " << endl;
    for(int i = 0;i<AttributesListWidget->count();i++)
    {
        oss << "\t" <<  AttributesListWidget->item(i)->text().toStdString() << endl;
    }
    clipboard->setText(tr(oss.str().c_str()));
}
void MainWindow::on_OptimizationButton_clicked()
{
    if(!m_OptimizeRunning)
    {
        m_GraphWidget->clear();
        m_GraphWidget->update();
        AttributesListWidget->clear();
        TVEdit->clear();
        OptimizationFactory::SetLocks(m_Locks);
        OptimizationFactory::SetItems(m_Items);
        if(m_Optimizer != NULL)
        {
            delete m_Optimizer;
        }
        m_Optimizer = OptimizationFactory::CallFactory<Optimization>();
        m_Optimizer->setItems(m_Items);
        m_Optimizer->setEquip(getCurrentEquip());
        m_Optimizer->setLocked(m_Locks);
        m_Optimizer->EndSignal(boost::bind(&MainWindow::EndNotify, this));
        m_Optimizer->UpdateSignal(boost::bind(&MainWindow::UpdateNotify, this,_1));
        m_Optimizer->Character(m_Character);
        m_Optimizer->Optimize();
        OptimizationButton->setText("Abort Optimization");
        m_OptimizeRunning = true;
        handleButtons(false);
    }
    else
    {
        m_Optimizer->Abort(true);
    }
}
bool MainWindow::event(QEvent* event)
{
    if(event->type() == QEvent::User)
    {
        UpdateData();
    }
    else if(event->type() == static_cast<QEvent::Type>(QEvent::User+1))
    {
        m_GraphWidget->update();
    }
    return QWidget::event(event);
}
void MainWindow::populateEnchantBox(int number,const Item* item)
{
    const std::vector<Enchant>* enchants;
    std::vector<Enchant>::const_iterator it4;
    m_EnchantCboxes[number]->clear();
    if(item->Type() == 1 && item->Slot() == 11) // shield
    {
        enchants  = &Enchant::GetEnchants()->at(18);
    }
    else if(item->Type() == 4 && item->Slot() == 4) // twohand
    {
        enchants  = &Enchant::GetEnchants()->at(17);
    }
    else if(item->Type() == 1 && item->Slot() == 12) // offhhand
    {
        enchants = &Enchant::GetEnchants()->at(19);
    }
    else
    {
        enchants = &Enchant::GetEnchants()->at(number);
    }
    if(enchants->size() <= 1) enchants = 0;
    if(enchants && item->Id() != 99999)
    {
        for(it4 = enchants->begin();it4!= enchants->end();it4++)
        {
            m_EnchantCboxes[number]->addItem(&*it4); // bad
        }
        m_EnchantCboxes[number]->setCurrentIndex(m_EnchantCboxes[number]->findText(tr("None")));
        m_EnchantCboxes[number]->setEnabled(true);
    }
    else m_EnchantCboxes[number]->setEnabled(false);
}
void MainWindow::populateGemBoxes(int number,const Item* item)
{
    vector<const Item*>::iterator it;
    for(int i = 0;i<3;i++)
    {
        m_GemCboxes[number*3+i]->clear();
        if(i < item->Sockets()->Count())
        {
            m_GemCboxes[number*3+i]->setEnabled(true);
            bool ismeta = item->Sockets()->Colors()->at(i)== 8 ? true : false;
            int counter = 0;
            for(it = m_Items.at(weo::engine::Slotcount).begin();it!= m_Items.at(weo::engine::Slotcount).end();it++)
            {
                const Item* item2 = *it;
                if(ismeta && item2->Subtype() != 8 && item2->Id() != 99999) continue;
                else if(!ismeta && item2->Subtype() == 8 && item2->Id() != 99999) continue;
                m_GemCboxes[number*3+i]->addItem(item2);
                QPixmap pix(10,10);
                unsigned char color = item2->Subtype();
                // blue, red, yellow, meta
                int r = 0;
                int g = 0;
                int b = 0;
                if((color & 1) > 0)
                {
                    b = 255;
                }
                if((color & 2)  >0)
                {
                    r = 255;
                    if(b == 255)
                    {
                        r = 135;
                        b = 120;
                    }
                }
                if((color & 4) > 0)
                {
                    r = 255;
                    g = 255;
                    if(b == 255)
                    {
                        r = 0;
                        b = 0;
                    }
                }
                if(color == 8)
                {
                    r = 128;
                    g = 128;
                    b = 128;
                }                
                pix.fill(QColor(r,g,b));
                m_GemCboxes[number*3+i]->setItemIcon(counter,QIcon(pix));
                counter++;
            }
            m_GemCboxes[number*3+i]->setCurrentIndex(m_GemCboxes[number*3+i]->findText(tr("None")));
        }
        else m_GemCboxes[number*3+i]->setEnabled(false);
    }
}
void MainWindow::handleButtons(bool enable)
{
    LoadButton->setEnabled(enable);
    SaveButton->setEnabled(enable);
    BuffsButton->setEnabled(enable);
    CopyButton->setEnabled(enable);
    FilterButton->setEnabled(enable);
    BWListButton->setEnabled(enable);
    ConditionsButton->setEnabled(enable);
    EQVButton->setEnabled(enable);
}
void MainWindow::SlotCBox_currentIndexChanged(int index)
{
    if(m_Locked) return;
    int number = -1;
    ItemComboBox<Item> *cbox = reinterpret_cast<ItemComboBox<Item> *>(QObject::sender());
    number = m_SlotCboxes.indexOf(cbox);
    if(number < 0 || index < 0) return;
    const Item *item = m_Items[number][index];
    populateGemBoxes(number,item);
    populateEnchantBox(number,item);
    if(number == 14 && item->Slot() == 4)
    {
        m_Locked = true;
        m_SlotCboxes[number+1]->setCurrentIndex(m_SlotCboxes[number+1]->findText(tr("None")));
        m_Locked = false;
    }
    else if(number== 15 && m_SlotCboxes[number-1]->getCurrentItem()->Slot() == 4)
    {
        m_Locked = true;
        m_SlotCboxes[number-1]->setCurrentIndex(m_SlotCboxes[number-1]->findText(tr("None")));
        m_Locked = false;
    }
}
void MainWindow::EndNotify()
{
    QCoreApplication::postEvent(this,new QEvent(QEvent::User));
}
void MainWindow::UpdateTV(int index)
{
    if(m_Locked) return;
    m_GraphWidget->clear();
    m_GraphWidget->update();
    weo::engine::character::Equipment equip = getCurrentEquip();
    UpdateData(equip);
}
const weo::engine::character::Equipment MainWindow::getCurrentEquip()
{
    weo::engine::character::Equipment equip;
    equip.Fitness = 0;
    if(m_Character == NULL) return equip;
    for(int i = 0;i< weo::engine::Slotcount;i++)
    {
        equip.Items[i] =  m_SlotCboxes[i]->getCurrentItem();
        equip.Enchants[i] =  m_EnchantCboxes[i]->getCurrentItem();
        for(int k = 0;k<3;k++)
        {
            equip.Gems[i*3+k] = m_GemCboxes[i*3+k]->getCurrentItem();
        }
    }
    m_Character->evaluateBuffs();
    m_Character->evaluateEquip(equip.Items,equip.Gems,equip.Enchants);
    equip.Fitness = m_Character->evaluateTF();
    return equip;
}
void MainWindow::UpdateData(const weo::engine::character::Equipment& equip)
{
    m_Locked = true;
    handleButtons(true);
    for(int i = 0;i< weo::engine::Slotcount;i++)
    {
        const Item *item = equip.Items[i];
        if(item)
        {
            bool result = m_SlotCboxes[i]->setCurrentItem(item);
        }
        else m_SlotCboxes[i]->setCurrentIndex(m_SlotCboxes[i]->findText(tr("None")));
        populateGemBoxes(i,item);
        populateEnchantBox(i,item);
    }
    for(int i = 0;i< weo::engine::Slotcount*3;i++)
    {
        const Item *item = equip.Gems[i];
        if(item)
        {
            bool result = m_GemCboxes[i]->setCurrentItem(item);
        }
        else m_GemCboxes[i]->setCurrentIndex(m_GemCboxes[i]->findText(tr("None")));
    }
    for(int i = 0;i< weo::engine::Slotcount;i++)
    {
        const Enchant *item = equip.Enchants[i];
        if(item)
        {
            bool result = m_EnchantCboxes[i]->setCurrentItem(item);
        }
        else m_EnchantCboxes[i]->setCurrentIndex(m_EnchantCboxes[i]->findText(tr("None")));
    }
    TVLabel->setText(tr((m_Character->targetValue()+":").c_str()));
    QString tv;
    tv = tv.setNum(equip.Fitness);
    TVEdit->setText(tv);
    OutputAttributes(equip);
    m_Locked = false;
}
void MainWindow::UpdateData()
{
    m_OptimizeRunning = false;
    OptimizationButton->setText("Start Optimization");
    UpdateData(*m_Optimizer->getEquip());
}
void MainWindow::OutputAttributes(const weo::engine::character::Equipment& equip)
{
    m_Character->Equip().UseSpecial(false);
    m_Character->evaluateEquip(equip.Items,equip.Gems,equip.Enchants);
    m_Character->Equip().UseSpecial(true);
    const std::vector<const std::pair<std::string,float>> attrs = m_Character->getEquipValues();
    AttributesListWidget->clear();
    for(unsigned int i = 0;i<attrs.size();i++)
    {
        AttributesListWidget->addItem(tr(weo::engine::utility::Utility::toString(attrs[i].first,attrs[i].second).c_str()));
    }
}
void MainWindow::on_ClassCBox_currentIndexChanged(const QString &text)
{
    std::vector<std::string> builds = CharacterFactory::GetBuilds(text.toStdString());
    m_Character = NULL;
    BuildCBox->clear();
    std::vector<std::string>::iterator it;
    for(it = builds.begin();it!= builds.end();it++)
    {
        BuildCBox->addItem(tr(it->c_str()));
    }
}
void MainWindow::on_BuildCBox_currentIndexChanged(const QString &text)
{
    AttributesListWidget->clear();
    TVEdit->clear();
    std::string classname = ClassCBox->currentText().toStdString();
    std::string buildname = BuildCBox->currentText().toStdString();
    if(classname.empty() || buildname.empty()) return;
    Equipment equip = getCurrentEquip();
    m_Character = CharacterFactory::CallFactory<Character>(classname,buildname);
    m_Character->Database(Itemdatabase::getInstance());
    m_Items.clear();
    m_Character->filterEquip(m_Items);
    equip.filterEquip(m_Items);
    populateBoxes();
    if(equip.Fitness > 0)
    {

        m_Character->evaluateBuffs();
        m_Character->evaluateEquip(equip.Items,equip.Gems,equip.Enchants);
        equip.Fitness = m_Character->evaluateTF();
        UpdateData(equip);
    }
    m_OptimizeRunning = false;
    m_GraphWidget->clear();
    m_GraphWidget->update();
    GC_gcollect();
}
int MainWindow::loadData()
{
    CharacterFactory::RegisterClassBuild("Shaman","Enhancement",CharacterFactory::FactoryFunction<weo::engine::character::shaman::Enhancement>);
    CharacterFactory::RegisterClassBuild("Shaman","Restoration",CharacterFactory::FactoryFunction<weo::engine::character::shaman::Restoration>);
    CharacterFactory::RegisterClassBuild("Shaman","Elemental",CharacterFactory::FactoryFunction<weo::engine::character::shaman::Elemental>);
    CharacterFactory::RegisterClassBuild("Priest","Holy",CharacterFactory::FactoryFunction<weo::engine::character::priest::Holy>);
    CharacterFactory::RegisterClassBuild("Paladin","Holy",CharacterFactory::FactoryFunction<weo::engine::character::paladin::Holy>);
    CharacterFactory::RegisterClassBuild("Rogue","Combat",CharacterFactory::FactoryFunction<weo::engine::character::rogue::Combat>);
    CharacterFactory::RegisterClassBuild("Mage","Fire",CharacterFactory::FactoryFunction<weo::engine::character::mage::Fire>);
    CharacterFactory::RegisterClassBuild("Mage","Frost",CharacterFactory::FactoryFunction<weo::engine::character::mage::Frost>);
    CharacterFactory::RegisterClassBuild("Warlock","Affliction",CharacterFactory::FactoryFunction<weo::engine::character::warlock::Affliction>);
    CharacterFactory::RegisterClassBuild("Warlock","Destruction",CharacterFactory::FactoryFunction<weo::engine::character::warlock::Destruction>);
    CharacterFactory::RegisterClassBuild("Warrior","Protection",CharacterFactory::FactoryFunction<weo::engine::character::warrior::Protection>);
    CharacterFactory::RegisterClassBuild("Warrior","Fury",CharacterFactory::FactoryFunction<weo::engine::character::warrior::Fury>);
    CharacterFactory::RegisterClassBuild("Druid","Combat",CharacterFactory::FactoryFunction<weo::engine::character::druid::Combat>);
    OptimizationFactory::RegisterOptimizer("Full",100000000,OptimizationFactory::FactoryFunction<weo::engine::optimization::OptimizeFull>);
    OptimizationFactory::RegisterOptimizer("Partial",1,OptimizationFactory::FactoryFunction<weo::engine::optimization::OptimizePartial>);
    OptimizationFactory::RegisterOptimizer("Gems",0,OptimizationFactory::FactoryFunction<weo::engine::optimization::OptimizeGems>);
    if(!Itemdatabase::getInstance()->LoadDB("itemdb.xbz")) return -1;
    std::vector<std::string> classes= CharacterFactory::GetClasses();
    ClassCBox->clear();
    std::vector<std::string>::iterator it;
    for(it = classes.begin();it!= classes.end();it++)
    {
        ClassCBox->addItem(tr(it->c_str()));
    }
    memset(m_Locks,0,weo::engine::Slotcount*sizeof(bool));
    return 0;
}
void MainWindow::populateBoxes()
{
    vector<vector<const Item*>>::iterator it = m_Items.begin();
    vector<const Item*>::iterator it2;
    m_Locked = true;
    for(int i = 0;i< weo::engine::Slotcount;i++)
    {
        m_SlotCboxes[i]->clear();
        unsigned int counter = 0;
        for(it2 = it->begin();it2!= it->end();it2++)
        {		
            const Item *item = *it2;
            m_SlotCboxes[i]->addItem(item);
            size_t hash = item->Set()->Hash();
            if(hash > 0)
            {
                QPixmap pix(10,10);
                unsigned char r = ((hash % 0x1000000) >> 16) & 0xFF;
                unsigned char g = ((hash % 0x1000000) >> 8) & 0xFF;
                unsigned char b = ((hash % 0x1000000)) & 0xFF;
                pix.fill(QColor(r,g,b));
                m_SlotCboxes[i]->setItemIcon(counter,QIcon(pix));
            }
            counter++;
        }
        it++;
        m_SlotCboxes[i]->setCurrentIndex(m_SlotCboxes[i]->findText(tr("None")));
        const Item *item = m_SlotCboxes[i]->getCurrentItem();
        populateGemBoxes(i,item);
        populateEnchantBox(i,item);
    }
    m_Locked = false;
}